package com.sparrow.common.ai.behaviortree.factory;

import com.sparrow.common.ai.behaviortree.node.BehaviorNode;
import com.sparrow.common.ai.behaviortree.node.impl.*;
import org.jetbrains.annotations.NotNull;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * 行为树工厂 使用xml文件构建行为树
 */
public class BehaviorTreeFactory {

    public static final String VALUE_TRUE = "IsTrue";
    public static final String VALUE_FALSE = "IsFalse";

    /**
     * 使用xml文件构建行为树
     */
    public static BehaviorNode buildFromXml(File xmlFile) {
        try {
            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document doc = builder.parse(xmlFile);
            Element root = doc.getDocumentElement();
            return parseElement(root);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static BehaviorNode createNodeInstance(String className) {
        try {
            Class<?> clazz = Class.forName(className);
            return (BehaviorNode) clazz.getConstructor().newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 解析节点
     */
    private static BehaviorNode parseElement(Element elem) {
        String tagName = elem.getTagName();
        switch (tagName) {
            case "Sequence":
                return new SequenceNode(parseChildren(elem));
            case "Selector":
                return new SelectorNode(parseChildren(elem));
            case "Parallel":
                return new ParallelNode(parseChildren(elem));
            case "ConditionDecorate": {
                String valueDesc = getConditionValueDesc(elem);
                return new ConditionDecorateNode(parseChildren(elem), valueDesc.equals(VALUE_TRUE));
            }
            case "Condition": {
                String className = elem.getAttribute("class");
                String valueDesc = getConditionValueDesc(elem);
                ConditionNode node = (ConditionNode) createNodeInstance(className);
                node.setValue(valueDesc.equals(VALUE_TRUE));
                return node;
            }
            case "Action":
                String className = elem.getAttribute("class");
                BehaviorNode node = createNodeInstance(className);
                NodeList paramElements = elem.getElementsByTagName("Param");
                // 遍历 Param 节点
                for (int k = 0; k < paramElements.getLength(); k++) {
                    Node paramNode = paramElements.item(k);
                    Element paramElement = (Element) paramNode;
                    // 获取每个 Param 的 name 和 value 属性
                    String paramName = paramElement.getAttribute("name");
                    String paramValue = paramElement.getAttribute("value");
                    node.initParams(paramName, paramValue);
                }
                return node;
            default:
                throw new RuntimeException("Unknown tag: " + tagName);
        }
    }

    private static @NotNull String getConditionValueDesc(Element elem) {
        String valueDesc = elem.getAttribute("value");
        if (valueDesc == null || !valueDesc.equals(VALUE_FALSE)) {
            valueDesc = VALUE_TRUE;
        }
        return valueDesc;
    }

    private static List<BehaviorNode> parseChildren(Element parent) {
        NodeList children = parent.getChildNodes();
        List<BehaviorNode> list = new ArrayList<>();
        for (int i = 0; i < children.getLength(); i++) {
            Node n = children.item(i);
            if (n.getNodeType() == Node.ELEMENT_NODE) {
                list.add(parseElement((Element) n));
            }
        }
        return list;
    }

}